<template>
  <div class="chat">
    <div class="header">
      <div class="arrow-left">
        <ArrowLeft @click="backSessionList()"/>
      </div>
      <div class="avatar">
        <img :src="sessionUser.avatarUrl" alt=""/>
      </div>
      <div class="name">{{sessionUser.nickName}}</div>
    </div>
    <div class="content" ref="chatContent">
      <div v-for="message in sessionUser.messageList" :key="message.messageId">
        <div class="item item-left" v-if="message.sourceType === 1">
          <div class="avatar">
            <img :src="sessionUser.avatarUrl" alt="">
          </div>
          <div class="message-info">
            <div class="time">{{message.time}}</div>
            <div class="message-content">
              <div class="message" v-if="message.messageType === 1">{{message.message}}</div>
              <div class="image" v-else-if="message.messageType === 2">
                <img v-lazy="message.message.url" alt="" :style="'width:' + message.message.width + 'px;max-width:100%;aspect-ratio:' + message.message.width / message.message.height">
              </div>
            </div>
          </div>
        </div>
        <div class="item item-right" v-else-if="message.sourceType === 0">
          <div class="message-info">
            <div class="time">{{message.time}}</div>
            <div class="message-content">
              <div class="message" v-if="message.messageType === 1">{{message.message}}</div>
              <div class="image" v-else-if="message.messageType === 2">
                <img v-lazy="message.message.url" alt="" :style="'width:' + message.message.width + 'px;max-width:100%;aspect-ratio:' + message.message.width / message.message.height">
              </div>
              <div class="waiting" v-if="message.sending" @click="sendMessageNext(message)" title="点击重发"><Loading/></div>
            </div>
          </div>
          <div class="avatar">
            <img :src="currentUser.avatarUrl" alt=""/>
          </div>
        </div>
        <div class="item item-center" v-else><span>{{message.message}}</span></div>
      </div>
    </div>
    <div class="new-message" v-show="sessionUser.messageCount > 0" @click="scrollToBottom">查看最新消息</div>
    <div class="input-area">
      <div class="input">
        <input type="text" placeholder="输入消息" v-model="currentMessage" @keyup.enter="sendMessage">
      </div>
      <div class="button" @click="sendMessage">
        <Sending />
      </div>
      <div class="file" @click="selectFile">
        <input type="file" ref="refFileInput" placeholder="发送图片" style="display: none" @change="sendFile">
        <File />
      </div>
    </div>
  </div>
</template>

<script setup>
import File from "@/components/file.vue";
import ArrowLeft from "@/components/arrow-left.vue";
import Sending from "@/components/sending.vue";
import Loading from "@/components/loading.vue";
import {fileUpload, reqFilePolicy} from "@/api/index.js";
import {nextTick, onMounted, onUnmounted, ref, watch} from "vue";
import {readImage} from "@/util/ImageUtils.js";
import useSessionStore from "@/store/Session.js";
import useUserStore from "@/store/User.js";

const emits = defineEmits(["backList"])

const sessionStore = useSessionStore()
const userStore = useUserStore()
const sessionUser = sessionStore.getSession()
const currentUser = userStore.currUser

const currentMessage = ref("")

const refFileInput = ref(null)
const chatContent = ref(null)

function backSessionList() {
  emits("backList")
}

function sendMessage0(message) {
  sessionStore.sendMessage(message)
  scrollToBottom()
}

function sendMessageNext(message) {
  const newMessage = {
    sourceId: message.sourceId,
    targetId: message.targetId,
    message: message.message,
    sending: true,
    messageType: message.messageType
  }
  sendMessage0(newMessage)
}

function sendMessage() {
  if (currentMessage.value === "") {
    return
  }
  const message = {
    sourceId: currentUser.userId,
    targetId: sessionUser.userId,
    message: currentMessage.value,
    sending: true,
    messageType: 1
  }
  sendMessage0(message)
  currentMessage.value = ""
}

function selectFile() {
  refFileInput.value?.click()
}

async function sendFile() {
  if (refFileInput.value.files.length === 0) {
    return
  }
  const file = refFileInput.value.files[0]
  const policy = await reqFilePolicy({fileName: file.name})
  const formData = new FormData();
  for (const key in policy.data) {
    if (key === 'url') {
      continue
    }
    formData.append(key, policy.data[key])
  }
  formData.append("Content-Type", 'image/jpeg')
  formData.append('file', file)
  const [img, uploadRes] = await Promise.all([readImage(file), fileUpload(formData)])
  if (uploadRes.status === 204) {
    const message = {
      sourceId: currentUser.userId,
      targetId: sessionUser.userId,
      message: JSON.stringify({url:policy.data.url, height: img.height, width: img.width}),
      sending: true,
      messageType: 2
    }
    sendMessage0(message)
  }
}

function scrollToBottom() {
  nextTick(() => {
    chatContent.value.scrollTop = chatContent.value.scrollHeight
  })
}

async function scrollHandle() {
  if (chatContent.value === null) {
    return
  }
  const scrollTop = chatContent.value.scrollTop
  if (scrollTop < 10) {
    const oldHeight = chatContent.value.scrollHeight
    await sessionStore.getMessageList()
    const newTop = chatContent.value.scrollHeight - oldHeight
    if (newTop > 0) {
      chatContent.value.scrollTop = newTop
    }
  }
  if (chatContent.value.scrollHeight - chatContent.value.scrollTop - chatContent.value.clientHeight < 5) {
    sessionStore.scrollMessage()
  }
}

onMounted(() => {
  chatContent.value.addEventListener('scroll', scrollHandle, false)
})

onUnmounted(() => {
  if (chatContent.value) {
    chatContent.value.removeEventListener('scroll', scrollHandle, false)
  }
})

watch(() => sessionUser.userId, (value, oldValue) => {
  scrollToBottom()
}, {immediate: true})

watch(() => sessionUser.messageList, () => {
  // 距离底部小于50px时自动滚动到底部
  if (chatContent.value.scrollHeight - chatContent.value.scrollTop - chatContent.value.clientHeight < 50) {
    scrollToBottom()
  }
}, {deep: true})
</script>

<style scoped>

.chat {
  width: 100%;
  .header {
    display: flex;
    height: 70px;
    border-bottom: 1px solid #dee0e3;
    align-items: center;
    .arrow-left {
      width: 40px;
      height: 40px;
      margin-right: 10px;
    }
    .name {
      margin-left: 10px;
    }
  }
  .content {
    height: calc(100% - 140px);
    overflow-y: auto;
    .item {
      display: flex;
    }
    .item-center {
      font-size: 12px;
      color: #8f959e;
      justify-content: center;
      align-items: center;
    }
    .item-left,.item-right {
      .avatar {
        padding-top: 17px;
      }
      .message-info {
        padding: 0 10px;
        .time {
          visibility: hidden;
          height: 17px;
          font-size: 12px;
          color: #8f959e;
        }
        .message-content {
          display: flex;
          .message {
            background-color: #eff0f1;
            padding: 10px;
            border-radius: 10px;
            font-size: 15px;
          }
          .image  {
            max-width: 80%;
            img {
              width: 100%;
              height: 100%;
              border-radius: 10px;
            }
          }
        }
      }
    }
    .item-right {
      justify-content: right;
      .message-info {
        display: flex;
        flex-direction: column;
        align-items: flex-end;
        .message-content {
          flex-direction: row-reverse;
          align-items: center;
          .waiting {
            margin-right: 10px;
            cursor: pointer;
          }
        }
      }
    }
    .item-right:hover .time, .item-left:hover .time{
      visibility: visible !important;
    }
  }
  .input-area {
    border: 1px solid #dee0e3;
    border-radius: 10px;
    height: 46px;
    margin-top: 8px;
    display: flex;
    align-items: center;
    .input {
      height: 40px;
      padding: 0 10px;
      width: calc(100% - 80px);
      margin-right: 5px;
      input {
        width: 100%;
        height: 100%;
        border: 0;
        outline: none;
      }
    }
    .button, .file {
      height: 30px;
      cursor: pointer;
      width: 30px;
      margin: 10px 5px;
    }
  }
  .new-message {
    margin: -20px 40px 0 0;
    text-align: right;
    color: darkblue;
    font-size: 14px;
    cursor: pointer;
  }
}
</style>